package com.javasea.web.threadpool;

import java.util.ArrayList;
import java.util.concurrent.*;

/**
 *@ClassName A
 *@Description TODO
 *@Author longxiaonan@163.com
 *@Date 2022/5/5 0005 14:20
 */
public class ExecutorCompletionServiceDemo {
    public static void main(String[] args) throws Exception {
        test1();
//        test2();
    }

    /**
     * ExecutorService 测试
     * 耗时最久的-10s 异步任务最先进入 list 执行，所以在循环过程中获取这个 10s 的任务结果的时候，
     * get 操作会一直阻塞，直到 10s 异步任务执行完毕。即使 3s、5s 的任务早就执行完了，也得阻塞等待 10s 任务执行完。
     * @throws Exception
     */
    public static void test1() throws Exception{
        ExecutorService executorService = Executors.newCachedThreadPool();
        ArrayList<Future<String>> futureArrayList = new ArrayList<>();
        System.out.println("公司让你通知大家聚餐 你开车去接人");
        // 任务1
        Future<String> future10 = executorService.submit(() -> {
            System.out.println("总裁：我在洗脚 最近比较上火 要洗1个小时才能出来 你等会来接我吧");
            TimeUnit.SECONDS.sleep(10);
            System.out.println("总裁：1小时了 我洗完脚了。你来接吧");
            return "总裁洗完脚了";

        });
        futureArrayList.add(future10);

        // 任务2
        Future<String> future3 = executorService.submit(() -> {
            System.out.println("研发：我在洗脚 我比较快 要洗3分钟就可以出来 你等会来接我吧");
            TimeUnit.SECONDS.sleep(3);
            System.out.println("研发：3分钟 我洗完脚了。你来接吧");
            return "研发洗完脚了";
        });
        futureArrayList.add(future3);

        // 任务3
        Future<String> future6 = executorService.submit(() -> {
            System.out.println("中层管理：我在洗脚  要洗10分钟就可以出来 你等会来接我吧");
            TimeUnit.SECONDS.sleep(6);
            System.out.println("中层管理：10分钟 我洗完脚了。你来接吧");
            return "中层管理洗完脚了";
        });
        futureArrayList.add(future6);
        TimeUnit.SECONDS.sleep(1);
        System.out.println("都通知完了,等着接吧。");
        try {
            for (Future<String> future : futureArrayList) {
                String returnStr = future.get();
                System.out.println(returnStr + "，你去接他");
            }
            Thread.currentThread().join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * ExecutorCompletionService 测试
     * ExecutorService 添加到 ExecutorCompletionService中
     * 无需用Future列表来缓存Future结果
     * 直接completionService.take().get();获取结果
     * @throws Exception
     */
    public static void test2() throws Exception{
        ExecutorService executorService = Executors.newCachedThreadPool();
        ExecutorCompletionService<String> completionService = new ExecutorCompletionService(executorService);
        System.out.println("公司让你通知大家聚餐 你开车去接人");
        // 任务1
        completionService.submit(() -> {
            System.out.println("总裁：我在洗脚 最近比较上火 要洗1个小时才能出来 你等会来接我吧");
            TimeUnit.SECONDS.sleep(10);
            System.out.println("总裁：1小时了 我洗完脚了。你来接吧");
            return "总裁洗完脚了";

        });

        // 任务2
        completionService.submit(() -> {
            System.out.println("研发：我在洗脚 我比较快 要洗3分钟就可以出来 你等会来接我吧");
            TimeUnit.SECONDS.sleep(3);
            System.out.println("研发：3分钟 我洗完脚了。你来接吧");
            return "研发洗完脚了";
        });

        // 任务3
        completionService.submit(() -> {
            System.out.println("中层管理：我在洗脚  要洗10分钟就可以出来 你等会来接我吧");
            TimeUnit.SECONDS.sleep(6);
            System.out.println("中层管理：10分钟 我洗完脚了。你来接吧");
            return "中层管理洗完脚了";
        });
        TimeUnit.SECONDS.sleep(1);
        System.out.println("都通知完了,等着接吧。");
        for (int i = 0; i < 3; i++) {
            String returnStr = completionService.take().get();
            System.out.println(returnStr + "，你去接他");
        }
        Thread.currentThread().join();
    }

}
